package tcm.com.gistone.controller;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.tools.ant.util.StringUtils;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import tcm.com.gistone.database.config.GetBySqlMapper;
import tcm.com.gistone.database.entity.*;
import tcm.com.gistone.database.mapper.*;
import tcm.com.gistone.util.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


/**
 * @Author:renqiang
 * @Param:
 * @Description:文献相关接口：文献入库，成功统计数据等
 * @Date:9:29 2017/8/11
 */
@RestController
@RequestMapping( "book" )
public class BookController {
    private final static org.slf4j.Logger logger = LoggerFactory.getLogger(ClientUtil.class);
    @Autowired
    private SectionMapper sm;
    @Autowired
    private BookinfoMapper bm;
    @Autowired
    private KnowledgeMapper km;
    @Autowired
    private SpecialBookMapper sbm;
    @Autowired
    private WordMapper wm;
    @Autowired
    private DirectoryMapper dm;
    @Autowired
    private WsRelationMapper wsm;
    @Autowired
    private WordRelationMapper wrm;
    @Autowired
    private ThemeMapper tm;
    @Autowired
    private BookinfoMapper bim;
    @Autowired
    private ConfidenceMapper cm;
    @Autowired
    private SpecialMapper spm;
    @Autowired
    private WordsRelationMapper wordsRelationMapper;
    @Autowired
    private GetBySqlMapper gm;
    @Autowired
    private ConfigUtil configUtil;

    //文件路径
    private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss SSS");

    /*根据名称查找文献*/
    @RequestMapping( value = "selectByName", method = RequestMethod.POST )
    public EdatResult selectByName(HttpServletRequest request, HttpServletResponse response) throws IOException {
        try {
            ClientUtil.SetCharsetAndHeader(request, response);
            JSONObject data = JSONObject.fromObject(request.getParameter("data"));
            long specialId = data.getLong("specialId");//专题id
            String key = data.getString("key");
            String sql = "select book_name from tb_bookinfo where special_id = " + specialId + " and book_name like '%" + key + "%' order by book_name asc ";
            List<Map> list = gm.findRecords(sql);
            return EdatResult.ok(list);
        } catch (Exception e) {
            return EdatResult.build(1, "操作失败");
        }
    }

    /* 请求文献入库，入库步骤1 */
    @RequestMapping( value = "startRecord", method = RequestMethod.POST )
    @Transactional( rollbackFor = Exception.class )
    public EdatResult startRecord(HttpServletRequest request, HttpServletResponse response) throws Exception {
        try {
            ClientUtil.SetCharsetAndHeader(request, response);
            JSONObject data = JSONObject.fromObject(request.getParameter("data"));
            long bookId = data.getLong("bookId");
            Bookinfo bookinfo = bm.selectByPrimaryKey(bookId);
            if (bookinfo.getStatus() == 1) {
                bookinfo.setStatus(2);//更改状态为准备入库
                bm.updateByPrimaryKey(bookinfo);
                return EdatResult.ok();
            } else {
                return EdatResult.build(1, "入库失败");
            }
        } catch (Exception e) {
            e.printStackTrace();
            response.getWriter().write("{\"status\":\"1\",\"msg\":\"入库失败\",\"data\":\"\"}");
            throw e;
        }
    }

    /* 开始文献入库，入库步骤2 */
    @RequestMapping( value = "record", method = RequestMethod.POST )
    @Transactional( rollbackFor = Exception.class )
    public void recording(HttpServletRequest request, HttpServletResponse response) throws Exception {
        ClientUtil.SetCharsetAndHeader(request, response);
        JSONObject data = JSONObject.fromObject(request.getParameter("data"));
        if (!RegUtil.CheckParameter(data.getLong("bookId"), "Long", null, false)) {
            logger.warn("/book/record  参数错误");
        } else {
            long bookId = data.getLong("bookId");
            Bookinfo bookinfo = bm.selectByPrimaryKey(bookId);
            bookinfo.setStatus(3);//更改状态为正在入库
            bm.updateByPrimaryKey(bookinfo);
            storeBook(bookId);
        }
    }

    /* 开始文献批量入库 */
    @RequestMapping( value = "batchBuid", method = RequestMethod.POST )
    @Transactional
    public EdatResult batchBuid(HttpServletRequest request, HttpServletResponse response) throws Exception {
        ClientUtil.SetCharsetAndHeader(request, response);
        JSONObject data = JSONObject.fromObject(request.getParameter("data"));
        try {
            JSONArray array = data.getJSONArray("bookIds");
            long t1 = System.currentTimeMillis();
            FileUtil.writeToTxt(configUtil.getLogUrl(), " 开始构建");
            logger.info("开始构建");
            for (int i = 0; i < array.size(); i++) {
                long bookid = array.getLong(i);
                Bookinfo bookinfo = bm.selectByPrimaryKey(bookid);
                /*存在正在构建的数据无法重新构建*/
                if (bookinfo.getStatus() != 7) {
                    return EdatResult.build(1, "存在古籍状态现在无法重新构建");
                }
            }
            for (int i = 0; i < array.size(); i++) {
                long bookid = array.getLong(i);
                rebuild(bookid);
            }
            long t2 = System.currentTimeMillis();
            FileUtil.writeToTxt(configUtil.getLogUrl(), " 构建完成，耗时：" + (t2 - t1) / 1000 + "s");
            logger.info("构建完成，耗时：" + (t2 - t1) / 1000 + "s");
            return EdatResult.ok();
        } catch (Exception e) {
            e.printStackTrace();
            return EdatResult.build(1, "构建失败");
        }
    }

    /*重新构建书籍*/
    public void rebuild(Long bookId) throws Exception {
        Bookinfo bookinfo = bm.selectByPrimaryKey(bookId);
        if (bookinfo.getStatus() != 7) {
            return;
        }
        try {
            FileUtil.writeToTxt(configUtil.getLogUrl(), " 开始删除文献《" + bookinfo.getBookName() + "》已入库知识构建数据");
            logger.info("开始删除文献《" + bookinfo.getBookName() + "》已入库知识构建数据");
            bookinfo.setStatus(5);//更改状态为准备知识构建
            bm.updateByPrimaryKey(bookinfo);
            /*删除历史知识构建数据*/
            deleteRelationByBook(bookId);
            FileUtil.writeToTxt(configUtil.getLogUrl(), " 已删除文献《" + bookinfo.getBookName() + "》已入库数据");
            /*开始重拾构建书籍数据*/
            int flag=getWsRelationWithhBook(bookId);
            if(flag==0){
                throw new RuntimeException();
            }
        } catch (Exception e) {
            bookinfo.setStatus(0);//更改状态为异常
            bm.updateByPrimaryKey(bookinfo);
            throw e;
        }
    }

    /*文献入库*/
    public void storeBook(long bookId) throws Exception {
        Bookinfo bookinfo = bm.selectByPrimaryKey(bookId);
        String bookName = bookinfo.getBookName();
        logger.info("开始录入古籍《" + bookName + "》");
        FileUtil.writeToTxt(configUtil.getLogUrl(), " 开始录入古籍《" + bookName + "》");
        try {
            long t1 = System.currentTimeMillis();
            long specialId = bookinfo.getSpecialId();
            Special special = spm.selectByPrimaryKey(specialId);
            String dir = bookinfo.getDirUrl();
            String secUrl = configUtil.getUrl() + dir + "/section/" + bookinfo.getSectionFile();//正文文件路径
            String mapUrl = "";
            if (bookinfo.getMappingFile() != null) {
                mapUrl = configUtil.getUrl() + dir + "/mapping/" + bookinfo.getMappingFile();//图文映射文件路径
            }
            int flag = recordSection(bookId, secUrl, mapUrl);//文献入库，返回值为0时入库异常
            if (flag == 0) {
                bookinfo.setStatus(0);//入库失败
                bm.updateByPrimaryKey(bookinfo);
                logger.error("录入古籍失败《" + bookName + "》");
                FileUtil.writeToTxt(configUtil.getLogUrl(), " 录入古籍失败《" + bookName + "》");
                throw new RuntimeException();
            }
            /*存在知识提取文件时*/
            if (bookinfo.getKnowledgeFile() != null) {
                String knowledgeUrl = configUtil.getUrl() + dir + "/knowledge/" + bookinfo.getKnowledgeFile();
                if (specialId == 1) {
                    int flag1 = recordKnowledge(specialId, bookId, knowledgeUrl);
                }
            }
            bookinfo.setStatus(4);//更改状态为入库完成
            bm.updateByPrimaryKey(bookinfo);
            /*构建知识库*/
            int flag2 = getWsRelationWithhBook(bookId);/*返回值为0时构建失败*/
            if (flag2 == 0) {//构建失败
                bookinfo.setStatus(0);
                bm.updateByPrimaryKey(bookinfo);
                logger.error("录入古籍失败《" + bookName + "》");
                FileUtil.writeToTxt(configUtil.getLogUrl(), " 录入古籍失败《" + bookName + "》");
                throw new RuntimeException();
            }
            SpecialBook specialBook = new SpecialBook();
            specialBook.setBookId(bookId);
            specialBook.setSpecialId(specialId);
            sbm.insert(specialBook);//添加专题下书籍
            special.setStatus(1);//标记专题数据需更新
            spm.updateByPrimaryKey(special);
            long t2 = System.currentTimeMillis();
            logger.info("结束录入古籍《" + bookName + "》,耗时：" + (t2 - t1) / 1000 + "s");
            FileUtil.writeToTxt(configUtil.getLogUrl(), " 结束录入古籍《" + bookName + "》,耗时：" + (t2 - t1) / 1000 + "s");
        } catch (IOException e) {
            bookinfo.setStatus(0);
            bm.updateByPrimaryKey(bookinfo);
            logger.error("录入古籍失败《" + bookName + "》");
            FileUtil.writeToTxt(configUtil.getLogUrl(), " 录入古籍失败《" + bookName + "》");
            throw e;
        }
    }

    /*请求文献批量入库*/
    @RequestMapping( value = "startBatchStore", method = RequestMethod.POST )
    @Transactional
    public EdatResult startBatchStore(HttpServletRequest request, HttpServletResponse response) throws Exception {
        try {
            ClientUtil.SetCharsetAndHeader(request, response);
            JSONObject data = JSONObject.fromObject(request.getParameter("data"));
            List<Bookinfo> list = bm.selectUnStore();
            if (list.size() == 0) {
                logger.info("没有可入库文献");
                return EdatResult.build(1, "没有可入库文献");
            }
            logger.info("准备批量入库");
            long t1 = System.currentTimeMillis();
            for (Bookinfo bookinfo : list) {
                bookinfo.setStatus(2);//更改状态为准备入库
                bm.updateByPrimaryKey(bookinfo);
            }
            long t2 = System.currentTimeMillis();
            logger.info("准备完成，耗时：" + (t2 - t1) / 1000 + "s");
            return EdatResult.ok();
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("准备入库出错");
            response.getWriter().write("{\"status\":\"1\",\"msg\":\"准备入库出错\",\"data\":\"\"}");
            throw e;
        }
    }

    /*文献批量入库*/
    @RequestMapping( value = "batchStore", method = RequestMethod.POST )
    @Transactional( rollbackFor = Exception.class )
    public void batchStore(HttpServletRequest request, HttpServletResponse response) throws Exception {
        try {
            ClientUtil.SetCharsetAndHeader(request, response);
            JSONObject data = JSONObject.fromObject(request.getParameter("data"));
            List<Bookinfo> list = bm.selectReadyToStore();
            if (list.size() == 0) {
                logger.info("没有可入库文献");
                return;
            }
            logger.info("开始批量入库");
            long t1 = System.currentTimeMillis();
            List<String> list1 = new ArrayList<>();//已入库书籍
            for (Bookinfo bookinfo : list) {
                long bookId = bookinfo.getBookId();
                bookinfo.setStatus(3);//更改状态为正在入库
                bm.updateByPrimaryKey(bookinfo);
                /*开始入库*/
                storeBook(bookId);
                list1.add(bookinfo.getBookName());
            }
            long t2 = System.currentTimeMillis();
            logger.info("批量入库完成:" + list1.toString() + "，耗时：" + (t2 - t1) / 1000 + "s");
            FileUtil.writeToTxt(configUtil.getLogUrl(), " 批量入库完成:" + list1.toString() + "，耗时：" + (t2 - t1) / 1000 + "s");
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("批量入库出错");
            response.getWriter().write("{\"status\":\"1\",\"msg\":\"批量入库出错\",\"data\":\"\"}");
            FileUtil.writeToTxt(configUtil.getLogUrl(), " 批量入库出错");
            throw e;
        }
    }

    /*检查置信度是否需要更新*/
    @RequestMapping( value = "check", method = RequestMethod.POST )
    public EdatResult check(HttpServletRequest request, HttpServletResponse response) {
        try {
            ClientUtil.SetCharsetAndHeader(request, response);
            JSONObject data = JSONObject.fromObject(request.getParameter("data"));
            List<Special> list = spm.getRefreshAble();/*查询是否有需要更新置信度的专题*/
            Map map = new HashMap();
            if (list.size() > 0) {
                map.put("needFreshConfidence", "true");
                return EdatResult.ok(map);
            } else {
                map.put("needFreshConfidence", "false");
                return EdatResult.ok(map);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return EdatResult.build(1, "检查失败");
        }
    }

    /*知识构建*/
    @RequestMapping( value = "init", method = RequestMethod.POST )
    @Transactional
    public EdatResult initDatabase(HttpServletRequest request, HttpServletResponse response) {
        try {
            ClientUtil.SetCharsetAndHeader(request, response);
            JSONObject data = JSONObject.fromObject(request.getParameter("data"));

            long specialId = data.getLong("specialId");
            /*清空日志文件*/
            FileUtil.clearInfoForFile(configUtil.getLogUrl());
            long t1 = System.currentTimeMillis();
            synchronized (this) {
                List<Bookinfo> list = bm.selectAvai();
                if (list.size() > 0) {
                    return EdatResult.build(1, "存在正在构建的文献，重新构建失败");
                }
                String sql = "update tb_bookinfo set status = 4 where special_id = " + specialId + " and  status = 7 ";
                gm.update(sql);
            }
            FileUtil.writeToTxt(configUtil.getLogUrl(), " 开始知识构建");
            /*开始知识构建*/
            init(specialId);
            long t2 = System.currentTimeMillis();
            FileUtil.writeToTxt(configUtil.getLogUrl(), " 构建成功，耗时：" + (t2 - t1) / 1000 + "s");
            return EdatResult.build(0, "success");
        } catch (Exception e) {
            e.printStackTrace();
            FileUtil.writeToTxt(configUtil.getLogUrl(), " 构建失败");
            return EdatResult.build(1, "fail");
        }
    }

    /*本草库关系库重跑*/
    public void init(long specialId) throws Exception {
        try {
            Special special = spm.selectByPrimaryKey(specialId);
            FileUtil.writeToTxt(configUtil.getLogUrl(), " 清空（" + special.getSpecialName() + "）专题关系库");
            logger.info("清空" + special.getSpecialName() + "专题关系库，重新生成关系");
            long t1 = System.currentTimeMillis();
            /*删除专题下历史构建数据*/
            String sql = "delete from tb_words_relation  where book_id in (SELECT book_id from tb_special_book where special_id = " + specialId + " ) ";
            gm.delete(sql);
            String sql1 = "delete from tb_ws_relation where book_id in  (SELECT book_id from tb_special_book where special_id = " + specialId + " ) ";
            gm.delete(sql1);
            List<Bookinfo> list = bm.selectAvaiBySpecial(specialId);
            FileUtil.writeToTxt(configUtil.getLogUrl(), " 开始重新生成关系库");
            logger.info("开始重新生成（" + special.getSpecialName() + "）专题关系库");
            /*更改可构建书籍状态为准备构建*/
            String sql2 = "update tb_bookinfo set status = 5 where special_id = " + specialId + " and status = 4";
            gm.update(sql2);
            for (Bookinfo bookinfo : list) {
                /*知识构建*/
                getWsRelationWithhBook(bookinfo.getBookId());
            }
            long t2 = System.currentTimeMillis();
            FileUtil.writeToTxt(configUtil.getLogUrl(), " " + special.getSpecialName() + "专题重新生成关系完成，耗时：" + (t2 - t1) / 1000 + "s");
            logger.info(special.getSpecialName() + "重新生成关系库完成，耗时：" + (t2 - t1) / 1000 + "s");
            /*标记专题有更新*/
            special.setStatus(1);
            spm.updateByPrimaryKey(special);
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        }
    }

    /*更新置信度*/
    @RequestMapping( value = "generateConfidence" )
    @Transactional( rollbackFor = Exception.class )
    public EdatResult generateConfidence(HttpServletRequest request, HttpServletResponse response) throws Exception {
        try {
            ClientUtil.SetCharsetAndHeader(request, response);
            /*查询所有状态为2到7的书籍，判断是否有正在构建的书籍*/
            List<Bookinfo> list3 = bm.selectAvai();
            if (list3.size() > 0) {
                return EdatResult.build(1, "存在正在构建的文献，重新构建失败");
            }
            List<Special> list = spm.getRefreshAble();
            FileUtil.writeToTxt(configUtil.getLogUrl(), " 开始更新置信度");
            for (Special special : list) {
                /*更新置信度*/
                initConfidence(special.getSpecialId());
            }
            FileUtil.writeToTxt(configUtil.getLogUrl(), " 更新置信度完成");
            return EdatResult.ok();
        } catch (Exception e) {
            e.printStackTrace();
            logger.warn("置信度更新失败");
            FileUtil.writeToTxt(configUtil.getLogUrl(), " 置信度更新失败");
            response.getWriter().write("{\"status\":\"1\",\"msg\":\"置信度更新失败\",\"data\":\"\"}");
            throw e;
        }
    }

    /*更新专题置信度，置信度（0-1）*/
    public void initConfidence(long specialId) {
        Special special = spm.selectByPrimaryKey(specialId);
        logger.info("开始更新（" + special.getSpecialName() + "）专题置信度");
        FileUtil.writeToTxt(configUtil.getLogUrl(), " 开始更新（" + special.getSpecialName() + "）专题置信度");
        long t1 = System.currentTimeMillis();
        /*清空历史数据*/
        String del = "truncate table tb_confidence" + specialId;
        gm.delete(del);
        /*查询专题下主题词间关系数据*/
        String sql = "select sum(num) as sum,word_id,ano_word_id from (select T1.* from  tb_words_relation T1 join tb_bookinfo T2 on T1.book_id = T2.book_id and T2.special_id = " + specialId + " )T3  group by word_id ,ano_word_id";
        List<Map> list = gm.findRecords(sql);
        List<Confidence> list1 = new ArrayList<>();
        for (Map map : list) {
            int num = Integer.parseInt(map.get("sum").toString());//两个词同时出现在一段的数量
            long wordId1 = Long.parseLong(map.get("word_id").toString());
            long wordId2 = Long.parseLong(map.get("ano_word_id").toString());
            /*查询词1出现总次数*/
            int num1 = wsm.selectSumByWId(wordId1);
             /*查询词2出现总次数*/
            int num2 = wsm.selectSumByWId(wordId2);
            Confidence confidence = new Confidence();
            confidence.setWordId(wordId1);
            confidence.setAnoWordId(wordId2);
            confidence.setValue((float) num / num1);//设置置信度，（词1、词2出现在同一段总数）/词1总数
            Confidence confidence1 = new Confidence();
            confidence1.setWordId(wordId2);
            confidence1.setAnoWordId(wordId1);
            confidence1.setValue((float) num / num2);
            list1.add(confidence);
            list1.add(confidence1);
        }
        if (list1.size() > 0) {
            if (specialId == 1) {
                /*本草专题批量入库*/
                cm.insertBatch1(list1);
            } else if (specialId == 2) {
                  /*养生专题批量入库*/
                cm.insertBatch2(list1);
            } else if (specialId == 3) {
                  /*温病专题批量入库*/
                cm.insertBatch3(list1);
            }
        }
        special.setStatus(0);/*设置专题状态为无更新*/
        spm.updateByPrimaryKey(special);
        long t2 = System.currentTimeMillis();
        logger.info(special.getSpecialName() + "专题置信度更新成功，耗时：" + (t2 - t1) / 1000 + "s");
        FileUtil.writeToTxt(configUtil.getLogUrl(), special.getSpecialName() + "专题置信度更新成功，耗时：" + (t2 - t1) / 1000 + "s");
    }


    /*录入书目*/
    @RequestMapping( value = "recordBookinfo", method = RequestMethod.POST )
    @Transactional( rollbackFor = Exception.class )
    public EdatResult recordBookinfo(HttpServletRequest request, HttpServletResponse response) throws Exception {
        try {
            ClientUtil.SetCharsetAndHeader(request, response);
            JSONObject data = JSONObject.fromObject(request.getParameter("data"));
            long specialId = data.getLong("specialId");
            String name = data.getString("name");
            String author = data.getString("author");
            if (null != bm.selectOne(specialId, name)) {
                return EdatResult.build(1, "专题内题名重复");
            } else if (name == "" || name == null) {
                return EdatResult.build(1, "缺少题名");
            } else if (author == "" || author == null) {
                return EdatResult.build(1, "没有填写作者");
            }
            Bookinfo bookinfo = new Bookinfo();
            bookinfo.setBookName(name);
            bookinfo.setSpecialId(specialId);
            bookinfo.setNumber(data.getString("number"));//编码
            bookinfo.setApposeName(data.getString("alias"));//别名
            bookinfo.setSection(data.getString("juanshu"));//卷书
            bookinfo.setAuthor(author);
            bookinfo.setType(data.getString("type"));//类型
            bookinfo.setBookVersion(data.getString("version"));//版本
            bookinfo.setLocation(data.getString("location"));//地址
            bookinfo.setBookAbstract(data.getString("abstract"));//摘要
            bookinfo.setFeature(data.getString("feature"));//特色
            bookinfo.setDynasty(data.getString("dynasty"));//朝代
            bookinfo.setFinishYear(data.getString("year"));//年份
            bookinfo.setCopyState(data.getString("state"));//复制状态
            bookinfo.setNotes(data.getString("comment"));//备注
            bookinfo.setStatus(0);//设置状态为已上传
            bm.insert(bookinfo);
            Bookinfo bookinfo1 = bm.selectOne(specialId, name);
            Map map = new HashMap();
            /*返回书籍id*/
            map.put("bookId", bookinfo1.getBookId());
            return EdatResult.ok(map);
        } catch (Exception e) {
            e.printStackTrace();
            response.getWriter().write("{\"status\":\"1\",\"msg\":\"录入失败\",\"data\":\"\"}");
            throw e;
        }
    }

    /*更新书目*/
    @RequestMapping( value = "updateBookinfo", method = RequestMethod.POST )
    @Transactional( rollbackFor = Exception.class )
    public EdatResult updateBookinfo(HttpServletRequest request, HttpServletResponse response) throws Exception {
        try {
            ClientUtil.SetCharsetAndHeader(request, response);
            JSONObject data = JSONObject.fromObject(request.getParameter("data"));
            long id = data.getLong("id");
            Bookinfo bookinfo = bm.selectByPrimaryKey(id);
            bookinfo.setNumber(data.getString("number"));
            bookinfo.setBookName(data.getString("name"));
            bookinfo.setApposeName(data.getString("alias"));
            bookinfo.setSection(data.getString("juanshu"));
            bookinfo.setAuthor(data.getString("author"));
            bookinfo.setType(data.getString("type"));
            bookinfo.setBookVersion(data.getString("version"));
            bookinfo.setLocation(data.getString("location"));
            bookinfo.setBookAbstract(data.getString("abstract"));
            bookinfo.setFeature(data.getString("feature"));
            bookinfo.setDynasty(data.getString("dynasty"));
            bookinfo.setFinishYear(data.getString("year"));
            bookinfo.setCopyState(data.getString("state"));
            bookinfo.setNotes(data.getString("comment"));
            bm.updateByPrimaryKey(bookinfo);
            return EdatResult.ok();
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("更新书目失败");
            response.getWriter().write("{\"status\":\"1\",\"msg\":\"更新书目失败\",\"data\":\"\"}");
            throw e;
        }
    }

    /*查询古籍*/
    @RequestMapping( value = "getAllBooks", method = RequestMethod.POST )
    public Map getAllBooks(HttpServletRequest request, HttpServletResponse response) {
        try {
            ClientUtil.SetCharsetAndHeader(request, response);
            int pageNumber = Integer.parseInt(request.getParameter("pageNumber"));//页码
            int pageSize = Integer.parseInt(request.getParameter("pageSize"));
            String keyWord = request.getParameter("keyWord");//书目或作者
            keyWord = StringUtils.replace(keyWord, "_", "\\_");
            keyWord = StringUtils.replace(keyWord, "%", "\\%");//字符转义
            long specialId = Long.parseLong(request.getParameter("specialId"));
            String sql = "";
            String sql1 = "";
            String sql2 = "";
            if (!keyWord.equals("")) {
                sql2 = " and (book_name like  '%" + keyWord + "%' or author like '%" + keyWord + "%')";
            }
            if (specialId == 0) {
                sql = "select * from tb_bookinfo where 1=1 " + sql2 + "  limit " + pageNumber + "," + pageSize;
                sql1 = "select count(*) as total from tb_bookinfo where  1=1 " + sql2;
            } else {
                sql = "select * from tb_bookinfo where special_id = " + specialId + sql2 + " limit " + pageNumber + "," + pageSize;
                sql1 = "select count(*) as total from tb_bookinfo where special_id = " + specialId + sql2;
            }
            List<Map> result = new ArrayList<>();
            result = gm.findRecords(sql);
            int total = gm.findrows(sql1);
            Map map = new HashMap();
            map.put("total", total);
            map.put("rows", result);
            map.put("page", pageNumber / pageSize);
            return map;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /*删除书籍*/
    @RequestMapping( value = "deleteBook", method = RequestMethod.POST )
    @Transactional
    public EdatResult deleteBook(HttpServletRequest request, HttpServletResponse response) throws Exception {
        try {
            ClientUtil.SetCharsetAndHeader(request, response);
            List<Bookinfo> list = bm.selectAvai();
            /*构建中的书籍无法删除*/
            if (list.size() > 0) {
                return EdatResult.build(1, "存在正在构建的文献，重新构建失败");
            }
            JSONObject data = JSONObject.fromObject(request.getParameter("data"));
            long bookId = data.getLong("bookId");
            Bookinfo bookinfo = bm.selectByPrimaryKey(bookId);
            long specialid = bookinfo.getSpecialId();
            long t1 = System.currentTimeMillis();
            if (bookinfo.getStatus() == 9) {
                return EdatResult.build(1, "正在删除");
            }
            /*设置状态为正在删除*/
            bookinfo.setStatus(9);
            bm.updateByPrimaryKey(bookinfo);
            logger.info("开始删除文献《" + bookinfo.getBookName() + "》");
            FileUtil.writeToTxt(configUtil.getLogUrl(), " 开始删除文献《" + bookinfo.getBookName() + "》");
            /*从专题——书籍关联表里删除该书的记录*/
            String sql3 = "delete from tb_special_book where book_id = " + bookId;
            gm.delete(sql3);
            bm.deleteByPrimaryKey(bookId);
            if (specialid == 1) {
                String sql = "delete from tb_knowledge where book_id = " + bookId;
                gm.delete(sql);
            } else if (specialid == 3) {
               /* String sql = "delete from tb_warm_knowledge where book_id = " + bookId;
                gm.delete(sql);*/
            }
            /*删除书籍段落*/
            String sql1 = " delete from tb_section where book_id = " + bookId;
            gm.delete(sql1);
            /*删除书籍目录信息*/
            String sql2 = "delete from tb_directory where book_id = " + bookId;
            gm.delete(sql2);
            /*删除书籍分组信息*/
            String sql4 = "delete from tb_group_book where book_id = " + bookId;
            gm.delete(sql4);
            /*删除构建关系*/
            deleteRelationByBook(bookId);
            /*删除书籍文件*/
            FileUtil.delete(FileController.fileDir + bookinfo.getDirUrl());
            long specialId = bookinfo.getSpecialId();
            Special special = spm.selectByPrimaryKey(specialId);
            /*标记专题状态为有更新*/
            special.setStatus(1);
            spm.updateByPrimaryKey(special);
            long t2 = System.currentTimeMillis();
            logger.info("成功删除文献《" + bookinfo.getBookName() + "》，耗时：" + (t2 - t1) / 1000 + "s");
            FileUtil.writeToTxt(configUtil.getLogUrl(), " 成功删除文献《" + bookinfo.getBookName() + "》,耗时：" + (t2 - t1) / 1000 + "s");
            return EdatResult.ok();
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("删除文献失败");
            response.getWriter().write("{\"status\":\"1\",\"msg\":\"删除文献失败\",\"data\":\"\"}");
            throw e;
        }
    }

    /* 获取古籍信息*/
    @RequestMapping( value = "getBookinfo", method = RequestMethod.POST )
    public EdatResult getBookinfo(HttpServletRequest request, HttpServletResponse response) {
        try {
            ClientUtil.SetCharsetAndHeader(request, response);
            JSONObject data = JSONObject.fromObject(request.getParameter("data"));
            long bookId = data.getLong("bookId");
            Bookinfo bookinfo = bim.selectByPrimaryKey(bookId);
            Map map = new HashMap();
            map.put("data", bookinfo);
            return EdatResult.build(1, "success", map);
        } catch (Exception e) {
            e.printStackTrace();
            return EdatResult.build(0, "获取书目失败");
        }
    }

    /*获取书籍目录*/
    @RequestMapping( value = "getDirectory", method = RequestMethod.POST )
    public EdatResult getDirectory(HttpServletRequest request, HttpServletResponse response) {
        try {
            ClientUtil.SetCharsetAndHeader(request, response);
            JSONObject data = JSONObject.fromObject(request.getParameter("data"));
            long bookId = data.getLong("bookId");
            Map<String, Object> map = new HashMap();
            /*获取书籍目录信息*/
            List<Directory> list = dm.selectByBookIdAndLevel(bookId, 0);
            for (Directory dir : list) {
                map.put("children", setDir(dir.getId()));
                map.put("name", dir.getName());
                map.put("sectionId", dir.getSectionId());
                map.put("id", dir.getId());
                map.put("pageNum", dir.getPageNum());
                map.put("parentId", dir.getParentId());
            }
            return EdatResult.build(0, "success", map);
        } catch (Exception e) {
            e.printStackTrace();
            return EdatResult.build(1, "获取目录失败");
        }
    }

    /*生成目录树方法*/
    public List<Map> setDir(long id) {
        List list = new ArrayList();
        List<Directory> tem = dm.selectByParentId(id);/*查询当前目录的子目录*/
        if (tem.size() < 1) {
            return null;
        }
        for (Directory dir : tem) {
            Map<String, Object> map = new HashMap<>();
            map.put("children", setDir(dir.getId()));
            map.put("name", dir.getName());
            map.put("pageNum", dir.getPageNum());
            map.put("sectionId", dir.getSectionId());
            map.put("id", dir.getId());
            map.put("parentId", dir.getParentId());
            list.add(map);
        }
        return list;
    }

    /*获取书籍正文*/
    @RequestMapping( value = "getSection", method = RequestMethod.POST )
    public EdatResult getSection(HttpServletRequest request, HttpServletResponse response) {
        try {
            ClientUtil.SetCharsetAndHeader(request, response);
            JSONObject data = JSONObject.fromObject(request.getParameter("data"));
            long bookId = data.getLong("bookId");
            List<Section> list = sm.selectByBookId(bookId);
            return EdatResult.build(1, "查询成功", list);
        } catch (Exception e) {
            e.printStackTrace();
            return EdatResult.build(0, "查询失败");
        }
    }

    /*录入正文*/
    public int recordSection(long id, String secUrl, String mapUrl) throws IOException {
        Workbook book = null;
        try {
            String file_dir = secUrl;//正文文件路径
            logger.info("开始录入正文");
            long t1 = System.currentTimeMillis();
            book = ExcelUtil.getExcelWorkbook(file_dir);
            Sheet sheet = book.getSheetAt(0);
            int firstRowNum = sheet.getFirstRowNum();
            int lastRowNum = sheet.getLastRowNum();
            int startPos = 0;
            int endPos = 0;
            int pageNum = 1;
            int lines = 0;//总行数
            List<Section> list = new ArrayList<>();
            // 循环除了第一行的所有行
            for (int rowNum = firstRowNum + 1; rowNum <= lastRowNum; rowNum++) {
                // 获得当前行
                Row row = sheet.getRow(rowNum);
                if (row == null || row.getCell(0) == null || ExcelUtil.getCellValue(row.getCell(0)) == "") {
                    continue;
                } else {
                    String content = ExcelUtil.getCellValue(row.getCell(2));
                    Matcher m = Pattern.compile("(?m)^.*$").matcher(content);/**/
                    int line = 0;/*一段所占行数*/
                    while (m.find()) {
                        line += m.group().length() / 50 + 1;
                    }
                    lines += line;
                    int len = content.length();
                    endPos += len;
                    // 循环当前行
                    Section sec = new Section();
                    sec.setBookId(id);
                    sec.setSectionContent(content);
                    sec.setSectionType(ExcelUtil.getCellValue(row.getCell(0)).split("<")[1].split(">")[0].trim());
                    sec.setSectionTitle(ExcelUtil.getCellValue(row.getCell(1)).trim());
                    sec.setStartPos(startPos);
                    sec.setEndPos(endPos);
                    sec.setNumber(pageNum);
                    list.add(sec);
                    startPos = endPos + 1;
                    /*超过24行，下一页*/
                    if (lines > 24) {
                        pageNum++;
                        lines = 0;
                    }
                }
            }
            if (list.size() > 0) {
                /*批量入库书籍正文*/
                sm.insertBatch(list);
            }
            long t2 = System.currentTimeMillis();
            logger.info("结束录入正文，耗时：" + (t2 - t1) / 1000 + "s");
            /*生成目录*/
            int flag1 = recordDirectory(id);
            /*有图片段落映射文件*/
            if (!mapUrl.equals("")) {
                /*映射段落图片*/
                mappingImages(mapUrl, id);
            }
            return 1;
        } catch (FileNotFoundException fi) {
            fi.printStackTrace();
            return 0;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        } finally {
            book.close();
        }
    }

    /*段落映射图片xml，弃用*/
    public int recordImages(String imageUrl, long id) {
        try {
            logger.info("开始生产段落图片关系");
            long t1 = System.currentTimeMillis();
            List<Section> list = sm.selectByBookId(id);
            SAXReader reader = new SAXReader();
            File file = new File(imageUrl);
            Document document = reader.read(file);
            Element root = document.getRootElement();
            Element group = root.element("group");
            List<Element> pics = group.elements();
            int listsize = list.size();
            for (int i = 0; i < listsize; i++) {
                Section sec = list.get(i);
                String[] tem = sec.getSectionTitle().split("/");
                String url = "";
                Set set = new HashSet();
                for (Element ele : pics) {
                    Element keys = ele.element("COMMENT");
                    if (keys == null) {
                        continue;
                    }
                    String kstr = keys.getText();
                    if (kstr.indexOf(tem[tem.length - 1]) != -1) {
                        Element Url = ele.element("file_URL");
                        url = Url.getTextTrim();
                        set.add(url);
                    }
                }
                int num = set.size();
                if (num == 1) {
                    sec.setImageUrl(url);
                    sm.updateByPrimaryKey(sec);
                } else if (num > 1) {
                    int start = i - num + 1;
                    int end = i + num - 1;
                    if (i < num) {
                        start = 0;
                    } else if (i + num > listsize) {
                        end = listsize;
                    }
                    for (int j = start; j < end; j++) {
                        String str = "";
                        for (int m = 0; m < num; m++) {
                            Section sec1 = list.get(j + m);
                            String[] tem1 = sec1.getSectionTitle().split("/");
                            if (num - m > 1) {
                                str += tem1[tem1.length - 1] + " ";
                            } else {
                                str += tem1[tem1.length - 1];
                            }
                        }
                        Set set1 = new HashSet();
                        for (Element ele : pics) {
                            Element keys1 = ele.element("COMMENT");
                            if (keys1 == null) {
                                continue;
                            }
                            String kstr1 = keys1.getText();
                            if (kstr1.indexOf(str) != -1) {
                                Element Url1 = ele.element("file_URL");
                                url = Url1.getTextTrim();
                                set1.add(url);
                                continue;
                            }
                        }
                        if (set1.size() > 0) {
                            sec.setImageUrl(url);
                            sm.updateByPrimaryKey(sec);
                        }
                    }
                }
            }
            long t2 = System.currentTimeMillis();
            logger.info("结束生成段落图片对应关系，耗时：" + (t2 - t1) / 1000 + "s");
            return 1;
        } catch (Exception e) {
            e.printStackTrace();
            logger.info("段落图片关系生成失败");
            return 0;
        }
    }

    /*段落映射图片excel*/
    public int mappingImages(String imageUrl, long id) throws IOException {
        Workbook book = null;
        try {
            logger.info("开始生成图文映射关系");
            long t1 = System.currentTimeMillis();
            book = ExcelUtil.getExcelWorkbook(imageUrl);
            Sheet sheet = book.getSheetAt(0);
            if (sheet == null) {
                logger.error("文件错误");
                return 0;
            }
            Bookinfo bookinfo = bm.selectByPrimaryKey(id);
            String url = bookinfo.getDirUrl() + "/images/pics/";
            int firstRowNum = sheet.getFirstRowNum();
            int lastRowNum = sheet.getLastRowNum();
            for (int i = firstRowNum; i < lastRowNum; i++) {
                Row row = sheet.getRow(i);
                if (row != null && !ExcelUtil.getCellValue(row.getCell(0)).equals("")) {
                    String words = ExcelUtil.getCellValue(row.getCell(1));
                    if (!words.equals("NULL") && !words.equals("")) {
                        String[] arr = words.split(";");
                        if (arr.length > 0) {
                            for (int j = 0; j < arr.length; j++) {
                                String word = arr[j].trim();
                                if (!word.equals("") && !ExcelUtil.getCellValue(row.getCell(2)).equals("")) {
                                    /*根据名称匹配目录*/
                                    List<Directory> list1 = dm.selectDirectoryByName(word, id);
                                    /*存在相应段落*/
                                    if (list1.size() > 0) {
                                        Directory directory = list1.get(0);
                                        directory.setImageUrl(url + ExcelUtil.getCellValue(row.getCell(2)));
                                        /*更新段落对应图片信息*/
                                        dm.updateByPrimaryKey(directory);
                                    }
                                }
                            }
                        }
                    }
                }
            }
            long t2 = System.currentTimeMillis();
            logger.info("结束生成图文映射关系，耗时：" + (t2 - t1) / 1000 + "s");
            return 1;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        } finally {
            book.close();
        }
    }

    /*生成目录*/
    public int recordDirectory(long id) throws IOException, DocumentException {
        try {
            logger.info("开始生成目录");
            long t1 = System.currentTimeMillis();
            List<Section> list = sm.selectByBookId(id);/*获取所有段落*/
            List<String> result = new ArrayList<String>();
            for (Section sec : list) {
                String title = sec.getSectionTitle();/*标题*/
                Long secId = sec.getSectionId();
                int num = sec.getNumber();
                String[] arr = title.split("/|\\\\");//匹配正反斜杠，筛分标题
                int len = arr.length;//目录级数
                if (len == 1) {
                    String str0 = arr[0].trim() + "," + arr[0].trim() + "," + 0 + "," + secId + "," + num;
                    result.add(str0);
                } else if (len == 2) {
                    String str0 = arr[0].trim() + "," + arr[0].trim() + "," + 0;
                    ;/*父级名称，子级名称，目录级别*/
                    String str = arr[0].trim() + "," + arr[1].trim() + "," + 1 + "," + secId + "," + num;/*父级名称，子级名称，目录级别，段落id，页码*/
                    result.add(str0);
                    result.add(str);
                } else if (len == 3) {
                    String str = arr[0].trim() + "," + arr[1].trim() + "," + 1;
                    String str1 = arr[1].trim() + "," + arr[2].trim() + "," + 2 + "," + secId + "," + num;
                    result.add(str);
                    result.add(str1);
                } else if (len == 4) {
                    String str = arr[0].trim() + "," + arr[1].trim() + "," + 1;
                    String str1 = arr[1].trim() + "," + arr[2].trim() + "," + 2;
                    String str2 = arr[2].trim() + "," + arr[3].trim() + "," + 3 + "," + secId + "," + num;
                    result.add(str);
                    result.add(str1);
                    result.add(str2);
                } else if (len == 5) {
                    String str = arr[0].trim() + "," + arr[1].trim() + "," + 1;
                    String str1 = arr[1].trim() + "," + arr[2].trim() + "," + 2;
                    String str2 = arr[2].trim() + "," + arr[3].trim() + "," + 3;
                    String str3 = arr[3].trim() + "," + arr[4].trim() + "," + 4 + "," + secId + "," + num;
                    result.add(str);
                    result.add(str1);
                    result.add(str2);
                    result.add(str3);
                } else if (len == 6) {
                    String str = arr[0].trim() + "," + arr[1].trim() + "," + 1;
                    String str1 = arr[1].trim() + "," + arr[2].trim() + "," + 2;
                    String str2 = arr[2].trim() + "," + arr[3].trim() + "," + 3;
                    String str3 = arr[3].trim() + "," + arr[4].trim() + "," + 4;
                    String str4 = arr[4].trim() + "," + arr[5].trim() + "," + 5 + "," + secId + "," + num;
                    result.add(str);
                    result.add(str1);
                    result.add(str2);
                    result.add(str3);
                    result.add(str4);
                } else if (len == 7) {
                    String str = arr[0].trim() + "," + arr[1].trim() + "," + 1;
                    String str1 = arr[1].trim() + "," + arr[2].trim() + "," + 2;
                    String str2 = arr[2].trim() + "," + arr[3].trim() + "," + 3;
                    String str3 = arr[3].trim() + "," + arr[4].trim() + "," + 4;
                    String str4 = arr[4].trim() + "," + arr[5].trim() + "," + 5;
                    String str5 = arr[5].trim() + "," + arr[6].trim() + "," + 6 + "," + secId + "," + num;
                    result.add(str);
                    result.add(str1);
                    result.add(str2);
                    result.add(str3);
                    result.add(str4);
                    result.add(str5);
                } else {
                    logger.warn("目录层级太深:{}，无法获取" + len);
                    return 0;
                }
            }
            List<String> list2 = new ArrayList<>();
            List<String> list3 = new ArrayList<>();
            for (String tem : result) {
                if (!list2.contains(tem.trim())) {
                    list2.add(tem.trim());
                }
                String[] arr = tem.split(",");
                if (arr.length > 3) {
                    list3.add(arr[0] + "," + arr[1] + "," + arr[2]);
                }
            }
            List<Directory> list1 = new ArrayList<>();
            for (String temp : list2) {
                String[] arry = temp.split(",");
                int level = Integer.parseInt(arry[2]);
                String name = arry[1];
                if (arry.length == 3) {/*非叶子级目录*/
                    if (!list3.contains(temp)) {
                        Directory directory = new Directory();
                        directory.setBookId(id);
                        directory.setParentName(arry[0]);
                        directory.setName(name);
                        directory.setLevel(level);
                        list1.add(directory);
                    }
                } else {/*叶子级目录*/
                    Directory directory = new Directory();
                    directory.setBookId(id);
                    directory.setParentName(arry[0]);
                    directory.setName(name);
                    directory.setLevel(level);
                    directory.setSectionId(Long.parseLong(arry[3]));
                    directory.setPageNum(Integer.parseInt(arry[4]));
                    list1.add(directory);
                }
            }
            if (list1.size() > 0) {
                /*批量入库*/
                dm.insertBatch(list1);
            }
            List<Directory> listDir = dm.selectByBookId(id);
            for (Directory tem : listDir) {
                /*设置目录的父id*/
                List<Long> li = dm.selectByName(tem.getParentName(), id);
                tem.setParentId(li.get(0));
                dm.updateByPrimaryKey(tem);
            }
            long t2 = System.currentTimeMillis();
            logger.info("结束生成目录，耗时：" + (t2 - t1) / 1000 + "s");
            return 1;
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("目录生成失败");
            return 0;
        }
    }

    /*添加一本书生成段落主题词关系*/
    public int getWsRelationWithhBook(long id) {
        Bookinfo bookinfo = bm.selectByPrimaryKey(id);
        long specialId = bookinfo.getSpecialId();
        bookinfo.setStatus(6);/*更改状态为正在知识构建*/
        bm.updateByPrimaryKey(bookinfo);
        try {
            logger.info("开始生成《" + bookinfo.getBookName() + "》中段落与主题词的关系");
            FileUtil.writeToTxt(configUtil.getLogUrl(), " 开始生成《" + bookinfo.getBookName() + "》中段落与主题词的关系");
            Long t1 = System.currentTimeMillis();
            List<Theme> themes = tm.selectThemeBySpecial(specialId);/*获取专题词所有类型*/
            List<Section> sections = sm.selectByBookId(id);/*获取所有段落*/
            for (Theme theme : themes) {
                List<WsRelation> list3 = new ArrayList<>();/*段落主题词列表*/
                long type = theme.getThemeId();
                List<Word> words = wm.selectByType(type);/*某类主题词*/
                for (Word word : words) {
                    String k = word.getWord();/*主题词或别名*/
                    Long kid = word.getParentId();/*主词id*/
                    for (Section section : sections) {
                        String text = section.getSectionContent();
                        if (text.indexOf(k) == -1) {/*如果当前段落不包含当前主题词*/
                            continue;
                        } else {
                            /*查询包含当前主题词的其他主题词或别名*/
                            String sql = "select word from tb_word where special_id = " + specialId + " and word != '" + k + "' and word like '%" + k + "%'";
                            List<Map> list = gm.findRecords(sql);
                            /*如果存在，剔除其他主题词或别名*/
                            if (list.size() > 0) {
                                for (Map map : list) {
                                    text = text.replace(map.get("word").toString(), "");
                                }
                            }
                            int f = 0;/*开始匹配位置*/
                            f = text.indexOf(k);/*在剔除后文件中匹配主题词*/
                            int num = 0;/*专题词出现次数*/
                            while (f != -1) {
                                f = text.indexOf(k, f + 1);
                                num++;
                            }
                            /*如果有匹配到结果*/
                            if (num > 0) {
                                long tid = section.getSectionId();
                                String stype = section.getSectionType();
                                WsRelation wsRelation = new WsRelation();
                                wsRelation.setSectionId(tid);
                                wsRelation.setWordId(kid);
                                wsRelation.setBookId(id);
                                wsRelation.setWordType(type);
                                wsRelation.setSecType(stype);
                                wsRelation.setWordNum(num);
                                list3.add(wsRelation);
                            }
                        }
                    }
                }
                if (list3.size() > 0) {
                    wsm.insertBatch(list3);
                }
            }
            Long t2 = System.currentTimeMillis();
            logger.info("结束生成段落与主题词的关系，耗时：" + (t2 - t1) / 1000 + "s");
            FileUtil.writeToTxt(configUtil.getLogUrl(), " 结束生成段落与主题词的关系，耗时：" + (t2 - t1) / 1000 + "s");
            int flag = addWordRelationByBook(id);
            if(flag==1){
                return 1;
            }else {
                return 0;
            }
        } catch (Exception e) {
            bookinfo.setStatus(0);
            bm.updateByPrimaryKey(bookinfo);
            e.printStackTrace();
            return 0;
        }
    }

    /*更新主题词之间关系*/
    public int addWordRelationByBook(long id) {
        Bookinfo bookinfo = bm.selectByPrimaryKey(id);
        try {
            logger.info("开始更新《" + bookinfo.getBookName() + "》中主题词关系");
            FileUtil.writeToTxt(configUtil.getLogUrl(), " 开始更新《" + bookinfo.getBookName() + "》中主题词关系");
            long t1 = System.currentTimeMillis();
            List<Section> list = sm.selectByBookId(id);/*所有段落*/
            for (Section sec : list) {
                List<WordsRelation> list3 = new ArrayList<>();
                List<WsRelation> list1 = wsm.selectBySId(sec.getSectionId());/*段落中出现的所有主题词记录*/
                if (list1.size() > 1) {
                    String secType = sec.getSectionType();
                    long secId = sec.getSectionId();
                    for (int i = 0; i < list1.size() - 1; i++) {
                        WsRelation wr1 = list1.get(i);
                        long type1 = wr1.getWordType();
                        int num1 = wr1.getWordNum();
                        long id1 = wr1.getWordId();
                        for (int j = i + 1; j < list1.size(); j++) {
                            WsRelation wr2 = list1.get(j);
                            long type2 = wr2.getWordType();
                            /*wordid对应wordType；anowordid对应anowordType，wordType小于anowordType*/
                            if (type1 < type2) {
                                int num2 = wr2.getWordNum();
                                long id2 = wr2.getWordId();
                                int num = num1 < num2 ? num1 : num2;/*取两个词出现的次数的最小值未共同出现次数*/
                                WordsRelation wordsRelation = new WordsRelation();
                                wordsRelation.setSecId(secId);
                                wordsRelation.setWordId(id1);
                                wordsRelation.setAnoWordId(id2);
                                wordsRelation.setWordType(type1);
                                wordsRelation.setAnoWordType(type2);
                                wordsRelation.setBookId(id);
                                wordsRelation.setSecType(secType);
                                wordsRelation.setNum(num);
                                list3.add(wordsRelation);
                            } else if (type1 > type2) {
                                int num2 = wr2.getWordNum();
                                long id2 = wr2.getWordId();
                                int num = num1 < num2 ? num1 : num2;
                                WordsRelation wordsRelation = new WordsRelation();
                                wordsRelation.setSecId(secId);
                                wordsRelation.setWordId(id2);
                                wordsRelation.setAnoWordId(id1);
                                wordsRelation.setWordType(type2);
                                wordsRelation.setAnoWordType(type1);
                                wordsRelation.setBookId(id);
                                wordsRelation.setSecType(secType);
                                wordsRelation.setNum(num);
                                list3.add(wordsRelation);
                            }
                        }
                    }
                }
                if (list3.size() > 0) {
                    /*批量插入*/
                    wordsRelationMapper.insertBatch(list3);
                }
            }
            long t2 = System.currentTimeMillis();
            logger.info("更新主题词关系完成，耗时：" + (t2 - t1) / 1000 + "s");
            FileUtil.writeToTxt(configUtil.getLogUrl(), " 《" + bookinfo.getBookName() + "》中更新主题词关系完成，耗时：" + (t2 - t1) / 1000 + "s");
            bookinfo.setStatus(7);//更改状态为构建完成
            bm.updateByPrimaryKey(bookinfo);
            return 1;
        } catch (Exception e) {
            bookinfo.setStatus(0);
            bm.updateByPrimaryKey(bookinfo);
            e.printStackTrace();
            logger.error("更新主题词关系失败");
            return 0;
        }
    }

    /*删除一本书中的主题词关系*/
    public void deleteRelationByBook(long bookId) {
        try {
            /*删除段落与词之间关系*/
            String sql1 = "delete from tb_ws_relation where book_id = " + bookId;
            gm.delete(sql1);
            /*删除主题词之间关系*/
            String sql2 = "delete from tb_words_relation where book_id = " + bookId;
            gm.delete(sql2);
            String sql11 = "delete from tb_ws_relation_copy where book_id = " + bookId;
            gm.delete(sql11);
            String sql22 = "delete from tb_words_relation_copy where book_id = " + bookId;
            gm.delete(sql22);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /*录入专家知识本草专题*/
    public int recordKnowledge(long specialId, long bookId, String file_dir) throws IOException {
        Workbook book = null;
        try {
            logger.info("开始录入专家知识");
            long t1 = System.currentTimeMillis();
            book = ExcelUtil.getExcelWorkbook(file_dir);
            Sheet sheet = book.getSheetAt(0);
            if (sheet == null) {
                logger.error("数据错误");
                return 0;
            }
            int firstRowNum = sheet.getFirstRowNum();
            int lastRowNum = sheet.getLastRowNum();
            List<Knowledge> list = new ArrayList<>();
            for (int i = firstRowNum + 1; i < lastRowNum; i++) {
                Row row = sheet.getRow(i);
                if (row != null && ExcelUtil.getCellValue(row.getCell(0)) != "") {
                    Knowledge knowledge = new Knowledge();
                    knowledge.setBookId(bookId);
                    knowledge.setSpecialId(specialId);
                    knowledge.setKnowledgeName(ExcelUtil.getCellValue(row.getCell(0)));
                    knowledge.setAlias(ExcelUtil.getCellValue(row.getCell(1)));
                    knowledge.setKnowledgeType(ExcelUtil.getCellValue(row.getCell(2)));
                    knowledge.setBirthEnv(ExcelUtil.getCellValue(row.getCell(3)));
                    knowledge.setPart(ExcelUtil.getCellValue(row.getCell(4)));
                    knowledge.setTaste(ExcelUtil.getCellValue(row.getCell(5)));
                    knowledge.setGas(ExcelUtil.getCellValue(row.getCell(6)));
                    knowledge.setChannelTropism(ExcelUtil.getCellValue(row.getCell(7)));
                    knowledge.setLift(ExcelUtil.getCellValue(row.getCell(8)));
                    knowledge.setToxicity(ExcelUtil.getCellValue(row.getCell(9)));
                    knowledge.setBeard(ExcelUtil.getCellValue(row.getCell(10)));
                    knowledge.setMake(ExcelUtil.getCellValue(row.getCell(11)));
                    knowledge.setHate(ExcelUtil.getCellValue(row.getCell(12)));
                    knowledge.setMurder(ExcelUtil.getCellValue(row.getCell(13)));
                    knowledge.setFear(ExcelUtil.getCellValue(row.getCell(13)));
                    knowledge.setAgainst(ExcelUtil.getCellValue(row.getCell(15)));
                    knowledge.setMainFunction(ExcelUtil.getCellValue(row.getCell(16)));
                    knowledge.setSymptom(ExcelUtil.getCellValue(row.getCell(17)));
                    knowledge.setDisease(ExcelUtil.getCellValue(row.getCell(18)));
                    knowledge.setComponent(ExcelUtil.getCellValue(row.getCell(19)));
                    knowledge.setUsages(ExcelUtil.getCellValue(row.getCell(20)));
                    knowledge.setProcessing(ExcelUtil.getCellValue(row.getCell(21)));
                    knowledge.setHarvest(ExcelUtil.getCellValue(row.getCell(22)));
                    knowledge.setGenuine(ExcelUtil.getCellValue(row.getCell(23)));
                    knowledge.setIdentification(ExcelUtil.getCellValue(row.getCell(24)));
                    knowledge.setUseLevel(ExcelUtil.getCellValue(row.getCell(25)));
                    knowledge.setRecording(ExcelUtil.getCellValue(row.getCell(26)));
                    knowledge.setOther(ExcelUtil.getCellValue(row.getCell(27)));
                    knowledge.setTaboo(ExcelUtil.getCellValue(row.getCell(28)));
                    knowledge.setSideEffect(ExcelUtil.getCellValue(row.getCell(29)));
                    knowledge.setDrugLike(ExcelUtil.getCellValue(row.getCell(30)));
                    knowledge.setAttention(ExcelUtil.getCellValue(row.getCell(31)));
                    knowledge.setFigure(ExcelUtil.getCellValue(row.getCell(32)));
                    list.add(knowledge);
                }
            }
            if (list.size() > 0) {
                km.insertBatch(list);
            }
            long t2 = System.currentTimeMillis();
            logger.info("结束录入专家知识，耗时：" + (t2 - t1) / 1000 + "s");
            return 1;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        } finally {
            book.close();
        }
    }
}
